package cn.congine.wizarpos.mall.action;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jdom.JDOMException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import cn.congine.wizarpos.mall.common.RespMessage;
import cn.congine.wizarpos.mall.model.SaleOrder;
import cn.congine.wizarpos.mall.model.SaleOrderItem;
import cn.congine.wizarpos.mall.model.WxOrder;
import cn.congine.wizarpos.mall.model.WxOrderDetail;
import cn.congine.wizarpos.mall.model.open.CateringSaleOrderUpdateAmountInput;
import cn.congine.wizarpos.mall.model.open.CateringSaleOrderUpdateAmountOutput;
import cn.congine.wizarpos.mall.model.open.Merchandise;
import cn.congine.wizarpos.mall.model.open.MerchandiseSyncInput;
import cn.congine.wizarpos.mall.model.open.MerchandiseSyncOutput;
import cn.congine.wizarpos.mall.model.open.MerchantDef;
import cn.congine.wizarpos.mall.model.open.MerchantDefQueryInput;
import cn.congine.wizarpos.mall.model.open.MerchantDefQueryOutput;
import cn.congine.wizarpos.mall.model.open.SaleOrderItemView;
import cn.congine.wizarpos.mall.model.open.SaleOrderView;
import cn.congine.wizarpos.mall.model.open.UpdateOrderInfoInput;
import cn.congine.wizarpos.mall.model.open.UpdateOrderInfoOutput;
import cn.congine.wizarpos.mall.model.open.WechartOrder;
import cn.congine.wizarpos.mall.model.open.WechartOrderDetailInput;
import cn.congine.wizarpos.mall.model.open.WechartOrderOutput;
import cn.congine.wizarpos.mall.model.open.WxPayUpdateInput;
import cn.congine.wizarpos.mall.model.open.WxPayUpdateOutput;
import cn.congine.wizarpos.mall.model.open.WxSaleOrderQueryInput;
import cn.congine.wizarpos.mall.model.open.WxSaleOrderQueryOutput;
import cn.congine.wizarpos.mall.service.impl.WPosHttpClient;
import cn.congine.wizarpos.mall.service.impl.WizarposOpenRestClient;
import cn.congine.wizarpos.mall.service.impl.WxHttpClient;
import cn.congine.wizarpos.mall.tenpay.PaymentPackage;
import cn.congine.wizarpos.mall.tenpay.WechatPayment;
import cn.congine.wizarpos.mall.tenpay.util.XMLUtil;
import cn.congine.wizarpos.mall.utils.SysConstants;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

@Controller
@RequestMapping(value = "/tenpay")
public class PayAction {
	private final Log log = LogFactory.getLog(getClass());

	private final String unifiedorder = "https://api.mch.weixin.qq.com/pay/unifiedorder";

	@Resource(name = "messageSource")
	private MessageSource messageSource;
	@Autowired
	private WxHttpClient wxHttpClient;

	@Autowired
	private WPosHttpClient wPosHttpClient;

	@Autowired
	private WizarposOpenRestClient wizarposOpenRestClient;

	@RequestMapping(value = "/pay")
	public ModelAndView toPayPage(@RequestParam(required = true) String mid,
			@RequestParam(required = true) String orderId,
			@RequestParam(required = true) String openId,
			@RequestParam(required = true) String dispatchType) {
		Map<String, Object> data = new HashMap<String, Object>();	
		UpdateOrderInfoInput input = new UpdateOrderInfoInput();
		input.setMid(mid);
		input.setOrderId(orderId);
		input.setDispatchType(dispatchType);
		UpdateOrderInfoOutput output = (UpdateOrderInfoOutput) wizarposOpenRestClient.post(input, "/order/update_orderinfo",UpdateOrderInfoOutput.class);
				
		data.put("orderId", orderId);
		data.put("mid", mid);
		return new ModelAndView("tenpay", data);
	}
	
	// 微信支付v2.7版本
	// @RequestMapping(value = "/message", method = RequestMethod.GET)
	// @ResponseBody
	// public RespMessage getPaymentMessage(@RequestParam(required = true)
	// String orderId,HttpServletRequest request) {
	// RespMessage res = new RespMessage();
	// SysMerchantDef sysMerchantDef=null;
	// WxOrder order = wxOrderService.getWxOrderByOrderId(orderId);
	// if (order == null) {
	// res.setCode(-1);
	// res.setMessage("无效支付请求：非法订单号");
	// log.warn("无效支付请求：非法订单号");
	// return res;
	// }
	// List<WxOrderDetail> orderItems =
	// wxOrderDetailService.getWxOrderDetailListByOrderId(orderId);
	// String notificationURL = getBaseURL(request) + "/tenpay/pay-notify";
	// log.debug(notificationURL);
	// try {
	// PaymentMessage pm = new PaymentMessage();
	// if (order != null) {
	// sysMerchantDef=sysMerchantDefService.getSysMerchantDefByMid(order.getMid());
	// }
	// String partner = sysMerchantDef.getWeixinMchId();
	// String partnerKey =sysMerchantDef.getWeixinPartnerKey();
	// String appKey = sysMerchantDef.getWeixinAppKey();
	// String appid = sysMerchantDef.getAppid();
	// pm.setPackage(partner, partnerKey, notificationURL,
	// request.getRemoteAddr(), order, orderItems);
	// pm.sign(appid, appKey);
	// res.setObj(pm);
	// return res;
	// } catch (MangoException e) {
	// log.error("生成订单支付报文失败");
	// res.setCode(-1);
	// res.setMessage("生成订单支付报文失败");
	// return res;
	// }
	// }

/*	// 微信支付v3.3.7版本
	@RequestMapping(value = "/message", method = RequestMethod.GET)
	@ResponseBody
	public RespMessage getPaymentMessage(
			@RequestParam(required = true) String orderId,
			HttpServletRequest request) {
		RespMessage res = new RespMessage();
		WxOrder order = wxOrderService.getWxOrderByOrderId(orderId);
		if (order == null) {
			res.setCode(-1);
			res.setMessage("无效支付请求：非法订单号");
			log.warn("无效支付请求：非法订单号");
			return res;
		}
		List<WxOrderDetail> orderItems = wxOrderDetailService
				.getWxOrderDetailListByOrderId(orderId);

		// 回调地址
		String notifyUrl = getBaseURL(request) + "/tenpay/pay-notify";
		log.debug(notifyUrl);

		SysWxChildMerchantToken sysMerchantDef = sysWxChildMerchantTokenService.getByWxAppIdAndMidAndPrimaryId(order.getMid());
		// 微信商户平台ID
		String partner = sysMerchantDef.getWxMchid();
		// 微信商户平台支付密钥
		String partnerKey = sysMerchantDef.getWxAppKey();
		// 微信公众平台应用ID
		String appid = sysMerchantDef.getWxAppId();
		// 交易商户支付信息
		if (StringUtils.isEmpty(appid) || StringUtils.isEmpty(partner) || StringUtils.isEmpty(partnerKey)) {
			res.setCode(-1);
			res.setMessage("商户信息不完整，无法发起支付");
			log.warn("商户信息不完整，无法发起支付");
			return res;
		}
		
		// 1.生成预支付回话标识
		String prepay_id = getPrepay_id(appid, partner, partnerKey, notifyUrl,
				request.getRemoteAddr(), order, orderItems);

		if (prepay_id == null) {
			res.setCode(-1);
			res.setMessage("请求异常，支付请求失败");
			log.warn("请求异常，支付请求失败");
			return res;
		}

		// 2.支付参数
		WechatPayment pm = new WechatPayment();
		pm.setPaymentPackage("prepay_id=" + prepay_id);
		pm.sign(appid, partnerKey);

		res.setObj(pm);
		return res;
	}*/
	
	// 微信支付v3.3.7版本
	@RequestMapping(value = "/message", method = RequestMethod.GET)
	@ResponseBody
	public RespMessage getPaymentMessage(
			@RequestParam(required = true) String mid,//add xudongdong
			@RequestParam(required = true) String orderId,
			HttpServletRequest request) {
		RespMessage res = new RespMessage();
		
		WechartOrderDetailInput wechartOrderDetailInput = new WechartOrderDetailInput();
		wechartOrderDetailInput.setMid(mid);
		wechartOrderDetailInput.setOrderId(orderId);
		WechartOrderOutput wechartOrderOutput = (WechartOrderOutput) wizarposOpenRestClient.post(wechartOrderDetailInput, "/order/detail", WechartOrderOutput.class);

		if (wechartOrderOutput == null) {//系统错误
			res.setCode(-1);
			res.setMessage("系统错误，操作失败，请重试");
			log.warn("系统错误，操作失败，请重试");
			return res;			
		}		
		if ("60020".equals(wechartOrderOutput.getCode())) {//60020 非法订单号
			res.setCode(-1);
			res.setMessage("无效支付请求：非法订单号");
			log.warn("无效支付请求：非法订单号");
			return res;			
		}		
		WechartOrder orderTemp = wechartOrderOutput.getResult();					
		WxOrder order = new WxOrder();
		try {
			BeanUtils.copyProperties(order, orderTemp);
		} catch (IllegalAccessException | InvocationTargetException e) {
			//do nothing
		}		
		List<WxOrderDetail> orderItems = orderTemp.getOrderDetail();

		// 回调地址
		String notifyUrl = getBaseURL(request) + "/tenpay/pay-notify";
		log.debug(notifyUrl);

		// 商户数据
		MerchantDefQueryInput merchantDefQueryInput = new MerchantDefQueryInput();
		merchantDefQueryInput.setMid(mid);
		MerchantDefQueryOutput merchantDefQueryOutput = (MerchantDefQueryOutput) wizarposOpenRestClient.post(merchantDefQueryInput, "/merchantdef/info", MerchantDefQueryOutput.class);				
		MerchantDef merchantDef = merchantDefQueryOutput.getResult();
		// 微信商户平台ID
		String partner = merchantDef.getWeixinMchId();
		// 微信商户平台支付密钥
		String partnerKey = merchantDef.getWeixinAppKey();
		// 微信公众平台应用ID
		String appid = merchantDef.getWeixinAppId();		
		
		// 交易商户支付信息
		if (StringUtils.isEmpty(appid) || StringUtils.isEmpty(partner) || StringUtils.isEmpty(partnerKey)) {
			res.setCode(-1);
			res.setMessage("商户信息不完整，无法发起支付");
			log.warn("商户信息不完整，无法发起支付");
			return res;
		}
		
		// 1.生成预支付回话标识
		String prepay_id = getPrepay_id(appid, partner, partnerKey, notifyUrl,
				request.getRemoteAddr(), order, orderItems);

		if (prepay_id == null) {
			res.setCode(-1);
			res.setMessage("请求异常，支付请求失败");
			log.warn("请求异常，支付请求失败");
			return res;
		}

		// 2.支付参数
		WechatPayment pm = new WechatPayment();
		pm.setPaymentPackage("prepay_id=" + prepay_id);
		pm.sign(appid, partnerKey);

		res.setObj(pm);
		return res;
	}
	
	/**
	 * 微信统一下单接口请求，获取微信生成的预支付回话标识prepay_id，用于后续接口调用中使用，该值有效期为2小时
	 * 
	 * @param partnerId
	 * @param partnerKey
	 * @param notifyUrl
	 * @param clientIP
	 * @param order
	 * @param orderItems
	 * @return
	 */
	public String getPrepay_id(String appid, String partnerId,
			String partnerKey, String notifyUrl, String clientIP,
			WxOrder order, List<WxOrderDetail> orderItems) {
		PaymentPackage pkg = new PaymentPackage();
		pkg.setAppid(appid);
		pkg.setMch_id(partnerId);
		pkg.setNotify_url(notifyUrl);
		pkg.setSpbill_create_ip(clientIP);
		pkg.assemble(order, orderItems);
		pkg.toSign(partnerKey);

		String xmlData = pkg.getPackageXML();

		String resp = wxHttpClient.postXML(unifiedorder, xmlData);
		String prepay_id = null;
		try {
			Map<String, String> respMap = XMLUtil.doXMLParse(resp);

			prepay_id = respMap.get("prepay_id");
		} catch (JDOMException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}

		return prepay_id;
	}
	
/*	// 微信二维码支付v3.3.7版本
	@RequestMapping(value = "/messageNative", method = RequestMethod.GET)
	@ResponseBody
	public RespMessage messageNative(
			@RequestParam(required = true) String orderId,
			HttpServletRequest request) {
		RespMessage res = new RespMessage();
		WxOrder order = wxOrderService.getWxOrderByOrderId(orderId);
		if (order == null) {
			res.setCode(-1);
			res.setMessage("无效支付请求：非法订单号");
			log.warn("无效支付请求：非法订单号");
			return res;
		}
		List<WxOrderDetail> orderItems = wxOrderDetailService
				.getWxOrderDetailListByOrderId(orderId);

		// 回调地址
		String notifyUrl = getBaseURL(request) + "/tenpay/pay-notify";
		log.debug(notifyUrl);

		SysWxChildMerchantToken sysMerchantDef = sysWxChildMerchantTokenService.getByWxAppIdAndMidAndPrimaryId(order.getMid());
		// 微信商户平台ID
		String partner = sysMerchantDef.getWxMchid();
		// 微信商户平台支付密钥
		String partnerKey = sysMerchantDef.getWxAppKey();
		// 微信公众平台应用ID
		String appid = sysMerchantDef.getWxAppId();
		// 交易商户支付信息
		if (StringUtils.isEmpty(appid) || StringUtils.isEmpty(partner) || StringUtils.isEmpty(partnerKey)) {
			res.setCode(-1);
			res.setMessage("商户信息不完整，无法发起支付");
			log.warn("商户信息不完整，无法发起支付");
			return res;
		}
		
		// 1.生成预支付二维码
		String cord_url = getCordUrl(appid, partner, partnerKey, notifyUrl,
				request.getRemoteAddr(), order, orderItems);

		if (cord_url == null) {
			res.setCode(-1);
			res.setMessage("请求异常，支付请求失败");
			log.warn("请求异常，支付请求失败");
			return res;
		}

		res.setObj(cord_url);
		return res;
	}*/
	
	// 微信二维码支付v3.3.7版本
	@RequestMapping(value = "/messageNative", method = RequestMethod.GET)
	@ResponseBody
	public RespMessage messageNative(
			@RequestParam(required = true) String mid,
			@RequestParam(required = true) String orderId,
			HttpServletRequest request) {
		RespMessage res = new RespMessage();
		
		WechartOrderDetailInput wechartOrderDetailInput = new WechartOrderDetailInput();
		wechartOrderDetailInput.setMid(mid);
		wechartOrderDetailInput.setOrderId(orderId);
		WechartOrderOutput wechartOrderOutput = (WechartOrderOutput) wizarposOpenRestClient.post(wechartOrderDetailInput, "/order/detail", WechartOrderOutput.class);

		if (wechartOrderOutput == null) {//系统错误
			res.setCode(-1);
			res.setMessage("系统错误，操作失败，请重试");
			log.warn("系统错误，操作失败，请重试");
			return res;			
		}		
		if ("60020".equals(wechartOrderOutput.getCode())) {//60020 非法订单号
			res.setCode(-1);
			res.setMessage("无效支付请求：非法订单号");
			log.warn("无效支付请求：非法订单号");
			return res;			
		}		
		WechartOrder orderTemp = wechartOrderOutput.getResult();					
		WxOrder order = new WxOrder();
		try {
			BeanUtils.copyProperties(order, orderTemp);
		} catch (IllegalAccessException | InvocationTargetException e) {
			//do nothing
		}		
		List<WxOrderDetail> orderItems = orderTemp.getOrderDetail();		
		
/*		WxOrder order = wxOrderService.getWxOrderByOrderId(orderId);
		if (order == null) {
			res.setCode(-1);
			res.setMessage("无效支付请求：非法订单号");
			log.warn("无效支付请求：非法订单号");
			return res;
		}
		List<WxOrderDetail> orderItems = wxOrderDetailService
				.getWxOrderDetailListByOrderId(orderId);*/

		// 回调地址
		String notifyUrl = getBaseURL(request) + "/tenpay/pay-notify";
		log.debug(notifyUrl);

		// 商户数据
		MerchantDefQueryInput merchantDefQueryInput = new MerchantDefQueryInput();
		merchantDefQueryInput.setMid(mid);
		MerchantDefQueryOutput merchantDefQueryOutput = (MerchantDefQueryOutput) wizarposOpenRestClient.post(merchantDefQueryInput, "/merchantdef/info", MerchantDefQueryOutput.class);				
		MerchantDef merchantDef = merchantDefQueryOutput.getResult();
		// 微信商户平台ID
		String partner = merchantDef.getWeixinMchId();
		// 微信商户平台支付密钥
		String partnerKey = merchantDef.getWeixinAppKey();
		// 微信公众平台应用ID
		String appid = merchantDef.getWeixinAppId();		
		// 交易商户支付信息
		if (StringUtils.isEmpty(appid) || StringUtils.isEmpty(partner) || StringUtils.isEmpty(partnerKey)) {
			res.setCode(-1);
			res.setMessage("商户信息不完整，无法发起支付");
			log.warn("商户信息不完整，无法发起支付");
			return res;
		}
		
		// 1.生成预支付二维码
		String cord_url = getCordUrl(appid, partner, partnerKey, notifyUrl,
				request.getRemoteAddr(), order, orderItems);

		if (cord_url == null) {
			res.setCode(-1);
			res.setMessage("请求异常，支付请求失败");
			log.warn("请求异常，支付请求失败");
			return res;
		}

		res.setObj(cord_url);
		return res;
	}
	
	/**
	 * 微信统一下单接口请求，获取微信生成的预支付二维码
	 * 
	 * @param partnerId
	 * @param partnerKey
	 * @param notifyUrl
	 * @param clientIP
	 * @param order
	 * @param orderItems
	 * @return
	 */
	public String getCordUrl(String appid, String partnerId,
			String partnerKey, String notifyUrl, String clientIP,
			WxOrder order, List<WxOrderDetail> orderItems) {
		PaymentPackage pkg = new PaymentPackage();
		pkg.setTrade_type("NATIVE");
		pkg.setAppid(appid);
		pkg.setMch_id(partnerId);
		pkg.setNotify_url(notifyUrl);
		pkg.setSpbill_create_ip(clientIP);
		pkg.assemble(order, orderItems);
		pkg.toSign(partnerKey);

		String xmlData = pkg.getPackageXML();

		String resp = wxHttpClient.postXML(unifiedorder, xmlData);
		String cord_url = null;
		try {
			Map<String, String> respMap = XMLUtil.doXMLParse(resp);

			cord_url = respMap.get("cord_url");
		} catch (JDOMException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}

		return cord_url;
	}

	/**
	 * v2.7版本，微信支付结束的回调操作，对订单修改操作
	 * 
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	// @RequestMapping(value = "/pay-notify", method = RequestMethod.POST)
	// public void acceptNotification(HttpServletRequest
	// request,HttpServletResponse response) throws Exception {
	// ResponseHandler resHandler = new ResponseHandler(request, response);
	// // String partner_param = resHandler.getParameter("partner");
	// // String partner = messageSource.getMessage("tenpay.partner", null,
	// Locale.ENGLISH);
	// //为本商户
	// // if(partner.equals(partner_param)){
	// //商户订单号
	// String orderId = resHandler.getParameter("out_trade_no");
	// //金额,以分为单位
	// String total_fee = resHandler.getParameter("total_fee");
	// //支付结果
	// String trade_state = resHandler.getParameter("trade_state");
	//
	// //判断签名及结果
	// if ("0".equals(trade_state)) {
	// WxOrder order = wxOrderService.getWxOrderByOrderId(orderId);
	// if (order == null) {
	// log.error("Invalid order ID [" + orderId + "]");
	// resHandler.sendToCFT("success");
	// return;
	// }
	//
	// if("1".equals(order.getPayStatus())){
	// log.error("Bad request:重复的支付交易:订单["+orderId+"]已支付");
	// resHandler.sendToCFT("fail");
	// return;
	// }
	// if(order.getAmount() == Integer.valueOf(total_fee)){
	// order.setPayStatus("1");
	// order.setStatus("1");
	// order.setLastTime(System.currentTimeMillis());
	// order.setPickUpQr(orderId);
	// wxOrderService.update(order);
	// //记录交易流水表
	// WxAddress address=wxAddressService.getWxAddressId(order.getAddressId());
	// String id=sysTableKeyService.getTranLogId();
	// PayTranLog payTranLog=new PayTranLog();
	// payTranLog.setId(id);
	// payTranLog.setpId(order.getMid());
	// payTranLog.setmId(order.getMid());
	// payTranLog.setTranTime(new Date());
	// payTranLog.setTranAmount(Integer.parseInt(total_fee));
	// payTranLog.setCardNo(address.getCardId());
	// payTranLog.setOrderNo(orderId);
	// payTranLog.setTranCode("814");
	// payTranLog.setTranDesc("微店订单");
	// payTranLog.setTranMark("微信支付");
	// payTranLog.setMasterTranLogId(id);
	// payTranLogService.save(payTranLog);
	//
	// log.debug("订单["+orderId+"]支付成功");
	// }else{
	// log.warn("订单["+orderId+"] 金额不符");
	// }
	// log.debug("success 后台通知成功");
	// //给财付通系统发送成功信息，财付通系统收到此结果后不再进行后续通知
	// } else {
	// log.debug("fail 支付失败");
	// }
	// resHandler.sendToCFT("success");
	// return;
	// // }else{
	// // resHandler.sendToCFT("fail");
	// // return;
	// // }
	// }

/*	*//**
	 * v3.3.7版本，微信支付结束的回调操作，对订单修改操作
	 * 
	 * @param request
	 * @param response
	 * @throws Exception
	 *//*
	@RequestMapping(value = "/pay-notify", method = RequestMethod.POST)
	public void acceptNotification(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(
				(ServletInputStream) request.getInputStream()));
		String line = null;
		StringBuilder sb = new StringBuilder();
		while ((line = br.readLine()) != null) {
			sb.append(line);
		}
		Map<String, String> resMap = XMLUtil.doXMLParse(sb.toString());
		// 支付结果
		String return_code = resMap.get("return_code");
		String result_code = resMap.get("result_code");
		
		log.error("--------------return_code------------");
		log.error(return_code);
		log.error("--------------result_code------------");
		log.error(result_code);
		
		// 判断签名及结果
		if ("SUCCESS".equals(return_code) && "SUCCESS".equals(result_code)) {
			// 商户订单号
			String orderId = resMap.get("out_trade_no");
			// 金额,以分为单位
			String total_fee = resMap.get("total_fee");
			
			WxOrder order = wxOrderService.getWxOrderByOrderId(orderId);
			if (order == null) {
				log.error("Invalid order ID [" + orderId + "]");
				sendToCFT(response,
						"<xml><return_code>SUCCESS</return_code></xml>");
				return;
			}
			String mid = order.getMid();
			String openId = order.getOpenId();
			
			log.error("--------------order.getAmount()------------");
			log.error(order.getAmount());
			log.error("--------------total_fee------------");
			log.error(total_fee);
			log.error("--------------order.getPayStatus()------------");
			log.error(order.getPayStatus());
			
			if ("1".equals(order.getPayStatus())) {
				log.error("Bad request:重复的支付交易-订单[" + orderId + "]已支付");
				sendToCFT(response,
						"<xml><return_code>FAIL</return_code></xml>");
				return;
			}
			if (order.getAmount() == Integer.valueOf(total_fee)) {
				log.error("--------------WeChart Pay Tran Log------------");
				log.error(orderId);
				
				order.setPayStatus("1");
				order.setStatus("1");
				order.setLastTime(System.currentTimeMillis());
				order.setPickUpQr(orderId);
				wxOrderService.update(order);
				// 记录交易流水表
				MrtMerchantCard card = mrtMerchantCardService.getMrtMerchantCard(mid,
						openId);
				wPosHttpClient.transactByRule(mid, openId, card.getCardNo(), 
						Integer.parseInt(total_fee), orderId, order.getDispatchType());

				log.debug("订单[" + orderId + "]支付成功");
			} else {
				log.warn("订单[" + orderId + "] 金额不符");
			}
			log.debug("success 后台通知成功");
			// 给财付通系统发送成功信息，财付通系统收到此结果后不再进行后续通知
		} else {
			log.error("fail 支付失败");
		}
		sendToCFT(response, "<xml><return_code>SUCCESS</return_code></xml>");
		return;
	}*/

	/**
	 * v3.3.7版本，微信支付结束的回调操作，对订单修改操作
	 * 
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	@RequestMapping(value = "/pay-notify", method = RequestMethod.POST)
	public void acceptNotification(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(
				(ServletInputStream) request.getInputStream()));
		String line = null;
		StringBuilder sb = new StringBuilder();
		while ((line = br.readLine()) != null) {
			sb.append(line);
		}
		Map<String, String> resMap = XMLUtil.doXMLParse(sb.toString());
		// 支付结果
		String return_code = resMap.get("return_code");
		String result_code = resMap.get("result_code");
		
		log.error("--------------return_code------------");
		log.error(return_code);
		log.error("--------------result_code------------");
		log.error(result_code);
		
		// 判断签名及结果
		if ("SUCCESS".equals(return_code) && "SUCCESS".equals(result_code)) {
			// 商户订单号
			String orderId = resMap.get("out_trade_no");
			// 金额,以分为单位
			String total_fee = resMap.get("total_fee");
			
			//请求开放平台微信支付更新接口
			WxPayUpdateInput input = new WxPayUpdateInput();
			input.setOrderId(orderId);
			input.setTotalFee(total_fee);
			WxPayUpdateOutput output = (WxPayUpdateOutput) wizarposOpenRestClient.post(input, "/wxshop/wxPayUpdate", WxPayUpdateOutput.class);
			WxOrder order = output.getWxOrder();
			if ("60020".equals(output.getCode())) {//非法订单号	
				log.error("Invalid order ID [" + orderId + "]");
				sendToCFT(response,
						"<xml><return_code>SUCCESS</return_code></xml>");
				return;
			}			
			log.error("--------------order.getAmount()------------");
			log.error(order.getAmount());
			log.error("--------------total_fee------------");
			log.error(total_fee);
			log.error("--------------order.getPayStatus()------------");
			log.error(order.getPayStatus());
			
			if ("60034".equals(output.getCode())) {//订单重复支付			
				log.error("Bad request:重复的支付交易-订单[" + orderId + "]已支付");
				sendToCFT(response,
						"<xml><return_code>FAIL</return_code></xml>");
				return;
			}
			if ("0".equals(output.getCode())) {//操作成功
				log.error("--------------WeChart Pay Tran Log------------");
				log.error(orderId);	

				//更新订单信息，记录交易流水表，已在微信支付更新接口中处理

				log.debug("订单[" + orderId + "]支付成功");
			} else {
				log.warn("订单[" + orderId + "] 金额不符");
			}
			log.debug("success 后台通知成功");
			// 给财付通系统发送成功信息，财付通系统收到此结果后不再进行后续通知
		} else {
			log.error("fail 支付失败");
		}
		sendToCFT(response, "<xml><return_code>SUCCESS</return_code></xml>");
		return;
	}
	
/*	@RequestMapping(value = "/status", method = RequestMethod.GET)
	@ResponseBody
	public String getOrderStatus(@RequestParam(required = true) String orderId,
			HttpServletRequest request) {
		log.debug("-------------------------------check status---");
		log.debug("orderId =" + orderId);
		WxOrder order = wxOrderService.getWxOrderByOrderId(orderId);
		if (order == null) {
			log.warn("非法订单号");
			return "非法订单号";
		}
		log.debug("order.getStatus() =" + order.getStatus());
		return order.getStatus();
	}*/

	@RequestMapping(value = "/status", method = RequestMethod.GET)
	@ResponseBody
	public String getOrderStatus(@RequestParam(required = true) String mid,
			@RequestParam(required = true) String orderId,
			HttpServletRequest request) {
		log.debug("-------------------------------check status---");
		log.debug("orderId =" + orderId);
		
		WechartOrderDetailInput input = new WechartOrderDetailInput();
		input.setMid(mid);
		input.setOrderId(orderId);
		WechartOrderOutput output = (WechartOrderOutput) wizarposOpenRestClient.post(input, "/order/detail", WechartOrderOutput.class);

		if (output == null) {//系统错误
			log.warn("系统错误，操作失败，请重试");
			return "系统错误，操作失败，请重试";		
		}		
		if ("60020".equals(output.getCode())) {//60020 非法订单号
			log.warn("非法订单号");
			return "非法订单号";	
		}		
		WechartOrder order = output.getResult();		

		log.debug("order.getPayStatus() =" + order.getPayStatus());
		return order.getPayStatus();
	}
	
	private String getBaseURL(HttpServletRequest httpRequest) {
		String url = "http://"
				+ messageSource.getMessage(SysConstants.SERVICE_DNS, null,
						Locale.ENGLISH);
		url += httpRequest.getSession().getServletContext().getContextPath();
		return url;
	}

	/**
	 * 返回处理结果给微信。
	 * 
	 * @param msg
	 *            Success or fail
	 * @throws IOException
	 */
	private void sendToCFT(HttpServletResponse response, String msg) {
		try {
			PrintWriter out = response.getWriter();
			out.println(msg);
			out.flush();
			out.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@RequestMapping(value = "/catering")
	public ModelAndView toCateringPayPage(
			@RequestParam(required = true) String orderId,
			@RequestParam(required = true) String openId,
			@RequestParam(required = true) String mid,
			@RequestParam(required = false) String sum,
			@RequestParam(required = false) String ticketInfoIds) {
		return new ModelAndView("catering_tenpay").addObject("openId", openId)
				.addObject("mid", mid).addObject("orderId", orderId)
				.addObject("ticketInfoIds", ticketInfoIds).addObject("sum", sum);
	}

//	@SuppressWarnings("unused")
//	private WechatPayment getTakeoutPaymentMessage(String openId,
//			String orderId, String notifyUrl, String remoteAddr) {
//		SaleOrder order = saleOrderService.getById(orderId);
//		if (order == null) {
//			return null;
//		}
//		List<SaleOrderItem> orderItems = saleOrderItemService
//				.getSaleOrderItemByOrderId(orderId);
//
//		SysMerchantDef sysMerchantDef = sysMerchantDefService
//				.getSysMerchantDefByMid(order.getMid());
//		// 微信商户平台ID
//		String partner = sysMerchantDef.getWeixinMchId();
//		// 微信商户平台支付密钥
//		String partnerKey = sysMerchantDef.getWeixinPartnerKey();
//		// 微信公众平台应用ID
//		String appid = sysMerchantDef.getAppid();
//
//		// 1.生成预支付回话标识
//		String prepay_id = getTakeoutPrepay_id(appid, partner, partnerKey,
//				notifyUrl, remoteAddr, order, orderItems, openId);
//
//		if (prepay_id == null) {
//			return null;
//		}
//
//		// 2.支付参数
//		WechatPayment pm = new WechatPayment();
//		pm.setPaymentPackage("prepay_id=" + prepay_id);
//		pm.sign(appid, partnerKey);
//
//		return pm;
//	}

/*	// 微信支付v3.3.7版本
	@RequestMapping(value = "/catering/message", method = RequestMethod.GET)
	@ResponseBody
	public RespMessage getTakeoutPaymentMessage(String openId,
			@RequestParam(required = true) String orderId,
			HttpServletRequest request) {
		RespMessage res = new RespMessage();
		SaleOrder order = saleOrderService.getById(orderId);
		if (order == null) {
			res.setCode(-1);
			res.setMessage("无效支付请求：非法订单号");
			log.warn("无效支付请求：非法订单号");
			return res;
		}
		List<SaleOrderItem> orderItems = saleOrderItemService
				.getSaleOrderItemByOrderId(orderId);

		// 回调地址
		String notifyUrl = getBaseURL(request) + "/tenpay/catering-pay-notify";
		log.debug(notifyUrl);

		SysWxChildMerchantToken sysMerchantDef = sysWxChildMerchantTokenService.getByWxAppIdAndMidAndPrimaryId(order.getMid());
		// 微信商户平台ID
		String partner = sysMerchantDef.getWxMchid();
		// 微信商户平台支付密钥
		String partnerKey = sysMerchantDef.getWxAppKey();
		// 微信公众平台应用ID
		String appid = sysMerchantDef.getWxAppId();
		
		// 交易商户支付信息
		if (StringUtils.isEmpty(appid) || StringUtils.isEmpty(partner) || StringUtils.isEmpty(partnerKey)) {
			res.setCode(-1);
			res.setMessage("商户信息不完整，无法发起支付");
			log.warn("商户信息不完整，无法发起支付");
			return res;
		}
		
		// 1.生成预支付回话标识
		String prepay_id = getTakeoutPrepay_id(appid, partner, partnerKey,
				notifyUrl, request.getRemoteAddr(), order, orderItems, openId);

		if (prepay_id == null) {
			res.setCode(-1);
			res.setMessage("请求异常，支付请求失败");
			log.warn("请求异常，支付请求失败");
			return res;
		}

		// 2.支付参数
		WechatPayment pm = new WechatPayment();
		pm.setPaymentPackage("prepay_id=" + prepay_id);
		pm.sign(appid, partnerKey);

		res.setObj(pm);
		return res;
	}
*/
	
	// 微信支付v3.3.7版本
	@RequestMapping(value = "/catering/message", method = RequestMethod.GET)
	@ResponseBody
	public RespMessage getTakeoutPaymentMessage(String openId,
			@RequestParam(required = true) String orderId,
			@RequestParam(required = true) String sum,
			HttpServletRequest request) {
		RespMessage res = new RespMessage();
		
		WxSaleOrderQueryInput wxSaleOrderQueryInput = new WxSaleOrderQueryInput();
		wxSaleOrderQueryInput.setOrderId(orderId);
		WxSaleOrderQueryOutput output = (WxSaleOrderQueryOutput) wizarposOpenRestClient.post(wxSaleOrderQueryInput, "/wxshop/wxSaleOrderQuery", WxSaleOrderQueryOutput.class);
		
		if (output == null) {//系统错误	
			res.setCode(-1);
			res.setMessage("系统错误，操作失败，请重试");
			log.warn("系统错误，操作失败，请重试");
			return res;			
		}		
		if ("60020".equals(output.getCode())) {//60020 非法订单号
			res.setCode(-1);
			res.setMessage("无效支付请求：非法订单号");
			log.warn("无效支付请求：非法订单号");
			return res;
		}		
		SaleOrderView orderTemp = output.getResult();					
		SaleOrder order = new SaleOrder();		
		try {
			BeanUtils.copyProperties(order, orderTemp);
			order.setAmount(amount2DB(sum));
		} catch (IllegalAccessException | InvocationTargetException e) {
			//do nothing
		}
		
		List<SaleOrderItem> orderItems = new ArrayList<SaleOrderItem>();
		List<SaleOrderItemView> saleOrderItemView = orderTemp.getSaleOrderItems();
		if (saleOrderItemView != null) {
			for (SaleOrderItemView itemView : saleOrderItemView)	{
				SaleOrderItem it = new SaleOrderItem();
				try {
					BeanUtils.copyProperties(it, itemView);
				} catch (IllegalAccessException | InvocationTargetException e) {
					//do nothing
				}
				orderItems.add(it);
			}
		}		

		CateringSaleOrderUpdateAmountInput input = new CateringSaleOrderUpdateAmountInput();
		input.setMid(order.getMid());
		input.setOrderId(order.getId());
		input.setAmount(sum);
		wizarposOpenRestClient.post(input, "/catering/update/amount", CateringSaleOrderUpdateAmountOutput.class);				
		
		// 回调地址
		String notifyUrl = getBaseURL(request) + "/tenpay/catering-pay-notify";
		log.debug(notifyUrl);

		// 商户数据
		MerchantDefQueryInput merchantDefQueryInput = new MerchantDefQueryInput();
		merchantDefQueryInput.setMid(orderTemp.getMid());
		MerchantDefQueryOutput merchantDefQueryOutput = (MerchantDefQueryOutput) wizarposOpenRestClient.post(merchantDefQueryInput, "/merchantdef/info", MerchantDefQueryOutput.class);				
		MerchantDef merchantDef = merchantDefQueryOutput.getResult();
		// 微信商户平台ID
		String partner = merchantDef.getWeixinMchId();
		// 微信商户平台支付密钥
		String partnerKey = merchantDef.getWeixinAppKey();
		// 微信公众平台应用ID
		String appid = merchantDef.getWeixinAppId();				
		// 交易商户支付信息
		if (StringUtils.isEmpty(appid) || StringUtils.isEmpty(partner) || StringUtils.isEmpty(partnerKey)) {
			res.setCode(-1);
			res.setMessage("商户信息不完整，无法发起支付");
			log.warn("商户信息不完整，无法发起支付");
			return res;
		}
		
		// 1.生成预支付回话标识
		String prepay_id = getTakeoutPrepay_id(appid, partner, partnerKey,
				notifyUrl, request.getRemoteAddr(), order, orderItems, openId);

		if (prepay_id == null) {
			res.setCode(-1);
			res.setMessage("请求异常，支付请求失败");
			log.warn("请求异常，支付请求失败");
			return res;
		}

		// 2.支付参数
		WechatPayment pm = new WechatPayment();
		pm.setPaymentPackage("prepay_id=" + prepay_id);
		pm.sign(appid, partnerKey);

		res.setObj(pm);
		return res;
	}
	
	/**
	 * 微信统一下单接口请求，获取微信生成的预支付回话标识prepay_id，用于后续接口调用中使用，该值有效期为2小时
	 * 
	 * @param partnerId
	 * @param partnerKey
	 * @param notifyUrl
	 * @param clientIP
	 * @param order
	 * @param orderItems
	 * @return
	 */
	public String getTakeoutPrepay_id(String appid, String partnerId,
			String partnerKey, String notifyUrl, String clientIP,
			SaleOrder order, List<SaleOrderItem> orderItems, String openId) {

		StringBuffer _body = new StringBuffer();
		for (SaleOrderItem item : orderItems) {
			if (item == null) {
				continue;
			}
			MerchandiseSyncInput producthotInput = new MerchandiseSyncInput();
			producthotInput.setMid(order.getMid());
			producthotInput.setProductId(item.getProductId());
			MerchandiseSyncOutput producthotOutput = (MerchandiseSyncOutput) wizarposOpenRestClient.post(producthotInput,"/product/merchandise",MerchandiseSyncOutput.class);
			List<Merchandise> products = producthotOutput.getResult();
			Merchandise pro = products.get(0);		
			if (pro != null && pro.getName() != null
					&& !pro.getName().isEmpty()) {
				_body.append(pro.getName());
				if (orderItems.size() > 1) {
					_body.append("...");
				}
				break;
			}
		}

		PaymentPackage pkg = new PaymentPackage();
		pkg.setAppid(appid);
		pkg.setMch_id(partnerId);
		pkg.setNotify_url(notifyUrl);
		pkg.setSpbill_create_ip(clientIP);
		pkg.assemble(order, _body.toString(), openId);
		pkg.toSign(partnerKey);

		String xmlData = pkg.getPackageXML();

		String resp = wxHttpClient.postXML(unifiedorder, xmlData);
		String prepay_id = null;
		try {
			Map<String, String> respMap = XMLUtil.doXMLParse(resp);
			if (respMap != null) {
				prepay_id = respMap.get("prepay_id");
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}

		return prepay_id;
	}

	/**
	 * v3.3.7版本，微信支付结束的回调操作，对订单修改操作
	 * 
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	@RequestMapping(value = "/catering-pay-notify", method = RequestMethod.POST)
	public void takeoutAcceptNotification(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(
				(ServletInputStream) request.getInputStream()));
		String line = null;
		StringBuilder sb = new StringBuilder();
		while ((line = br.readLine()) != null) {
			sb.append(line);
		}
		Map<String, String> resMap = XMLUtil.doXMLParse(sb.toString());
		// 支付结果
		String return_code = resMap.get("return_code");
		String result_code = resMap.get("result_code");

		// 判断签名及结果
		if ("SUCCESS".equals(return_code) && "SUCCESS".equals(result_code)) {
			// 商户订单号
			String orderNo = resMap.get("out_trade_no");
			// 金额,以分为单位
			String total_fee = resMap.get("total_fee");
			
			WxSaleOrderQueryInput wxSaleOrderQueryInput = new WxSaleOrderQueryInput();
			wxSaleOrderQueryInput.setOrderNo(orderNo);
			WxSaleOrderQueryOutput output = (WxSaleOrderQueryOutput) wizarposOpenRestClient.post(wxSaleOrderQueryInput, "/wxshop/wxSaleOrderQuery", WxSaleOrderQueryOutput.class);				
	
			if ("60020".equals(output.getCode())) {//60020 非法订单号
				log.error("Invalid order No [" + orderNo + "]");
				sendToCFT(response,
						"<xml><return_code>SUCCESS</return_code></xml>");
				return;
			}			
			SaleOrderView order = output.getResult();
			if ("1".equals(order.getPayStatus())) {
				log.error("Bad request:重复的支付交易:订单[" + orderNo + "]已支付");
				sendToCFT(response,
						"<xml><return_code>FAIL</return_code></xml>");
				return;
			}
			if (order.getAmount() == Integer.valueOf(total_fee)) {

				JSONObject param = new JSONObject();
				param.put("mid", order.getMid());
				param.put("orderId", order.getId());
				param.put("amount", order.getAmount());
				param.put("print", true);
				
				JSONObject payment = new JSONObject();
				payment.put("payType", "3");
				payment.put("amount", order.getAmount());
				
				JSONArray payments = new JSONArray();
				payments.add(payment);
				param.put("payments", payments);

				JSONObject respJson = null;
				try {
					respJson = wPosHttpClient.postOpen(
							"/catering/pay", param);
				} catch (Exception e) {
					log.error("订单[" + orderNo + "]支付成功，呼叫开放平台结算失败。");
				}

				if (respJson != null && "0".equals(respJson.getString("code"))) {
					log.debug("订单[" + orderNo + "]支付成功， 记录成功");
				} else {
					log.debug("订单[" + orderNo + "]错误，" + respJson);
				}
			} else {
				log.warn("订单[" + orderNo + "] 金额不符");
			}
			log.debug("success 后台通知成功");
			// 给财付通系统发送成功信息，财付通系统收到此结果后不再进行后续通知
		} else {
			log.debug("fail 支付失败");
		}
		sendToCFT(response, "<xml><return_code>SUCCESS</return_code></xml>");
		return;
	}
	
	@RequestMapping(value = "/catering/status", method = RequestMethod.GET)
	@ResponseBody
	public String getSaleOrderStatus(
			@RequestParam(required = true) String orderId,
			HttpServletRequest request) {
		log.debug("-------------------------------check status---");
		log.debug("orderId =" + orderId);
		WxSaleOrderQueryInput wxSaleOrderQueryInput = new WxSaleOrderQueryInput();
		wxSaleOrderQueryInput.setOrderId(orderId);
		WxSaleOrderQueryOutput output = (WxSaleOrderQueryOutput) wizarposOpenRestClient.post(wxSaleOrderQueryInput, "/wxshop/wxSaleOrderQuery", WxSaleOrderQueryOutput.class);				
		if (output == null) {//系统错误	
			log.warn("系统错误，操作失败，请重试");
			return "系统错误，操作失败，请重试";	
		}		
		if ("60020".equals(output.getCode())) {//60020 非法订单号
			log.warn("非法订单号");
			return "非法订单号";
		}			
		
		log.debug("order.getPayStatus() =" + output.getResult().getPayStatus());
		return output.getResult().getPayStatus();
	}	
	/**
	 * 金额存数据库乘以100
	 * 
	 * @param amount
	 * @return
	 * @throws NumberFormatException
	 */
	private static Integer amount2DB(String amount) throws NumberFormatException
	{
		int result = 0;
		if (amount != null && !"null".equals(amount)
				&& !amount.trim().isEmpty())
		{
			result = (int) (100 * Double.valueOf(amount));
		}
		return result;
	}
}
